home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 014 / libtools.arc / GRAF.AQM / GRAF.ASM
Encoding:
Assembly Source File  |  1984-04-08  |  24.6 KB  |  831 lines

  1.  
  2.  
  3.     PAGE  60,132
  4.     TITLE    EPSON MX-GRAFTRAX PrtSc, V 2.3a
  5. ; GRAF.COM  3/12/83
  6. ; INTERRUPT REPLACEMENT FOR PRINT SCREEN FUNCTION ON IBMPC(tm)
  7. ;  =====> N O T I C E <=======
  8. ;    THIS PROGRAM IS SUPPLIED FOR YOUR PERSONAL AND NON-COMMERCIAL
  9. ;    USE ONLY. NO COMMERCIAL USE PERMITTED. USERS OF THIS PROGRAM
  10. ;    ARE GRANTED LIMITED RIGHTS TO REPRODUCE AND DISTRIBUTE THIS
  11. ;    PROGRAM. IT MAY NOT BE SOLD. PROVIDING THIS PROGRAM FOR
  12. ;    CONSIDERATION ANY SORT, INCLUDING COPYING OR DISTRIBUTION FEES,
  13. ;    IS SPECIFICALLY PROHIBITED.  THE AUTHOR CANNOT ASSUME RESPONSIBILITY
  14. ;    FOR DAMAGES, REAL OR IMAGINED, RESULTING FROM THE USE OF THIS PROGRAM.
  15. ;  =====> ENDNOTICE <=========
  16. ;
  17. ;    PLEASE SEND PROBLEM REPORTS AND SUGGESTIONS TO:
  18. ;        MARTY SMITH
  19. ;        310 CINNAMON OAK LANE
  20. ;        HOUSTON, TEXAS    77079
  21. ;        SOURCE ST2259, COMPUSERVE 72155,1214
  22. ;        (713) 661-1241 Office, (713) 464-6737, Home.
  23. ;
  24. ;  THIS PROGRAM ORIGINALLY DESIGNED FOR EPSON-MX(tm) SERIES PRINTERS
  25. ;  WITH GRAFTRAX80(tm) AND GRAFTRAX+(tm) BIT-PLOT GRAPHIC CAPABILITES.
  26. ;  ======> Now modified with conditional compilation and macros for
  27. ;  ======> c.itoh(tm) model 8510a and other printers with bit-plot
  28. ;  ======> capabilities. See the macro definitions and equates following
  29. ;  ======> these messages.
  30. ;
  31. ;    CHANGE HISTORY:
  32. ;    9/18/82 - Buffer in routine for a line of bit-plot bytes to allow for
  33. ;  checking for blank lines replaced by pre-scan routine, saving space.
  34. ;    1/24/83 - Modifications for conditional assembly with other printers
  35. ;  and C.ITOH 8510a.
  36. ;    1/24/83 - Improved error checking for out-of-paper and I/O errors
  37. ;  involving printer.
  38. ;    1/24/83 - Bug in error check corrected, occuring when routine does
  39. ;  error exit and is then called again, resulting in bit-plot data sent in
  40. ;  regular mode.
  41. ;    3/12/83 - Allow calling as a subroutine. i.e. no shift key depressed.
  42. ;  Defaults to small print mode. Can be poked for LARGE.
  43. ;
  44. ;    THE IBM MACRO ASSEMBLER(tm) AND LINK(tm) WILL PRODUCE
  45. ;    GRAF.EXE, WHICH MUST BE CONVERTED TO A .COM PROGRAM BY
  46. ;    THE COMMAND FROM DOS -EXE2BIN-.
  47. ;        do this:
  48. ;    X>EXE2BIN GRAF.EXE GRAF.COM
  49. ;
  50. ;    Features:
  51. ;  Accepts ESC key exit, prescans to test for blank line
  52. ;  left shift prtsc = small graphics, right shift prtsc = big
  53. ;  Runs as a .COM type program under dos
  54. ;     resident until power down or reset.
  55. ;   1 = screen sent horiz. 320 bits in 480 mode
  56. ;   2 = screen sent vert. 400 bits double printed in 480 mode
  57. ; **************  1 mode **********************
  58. ;    DL = masking character
  59. ;    DH = count of 25 (physical lines)
  60. ;    CX = counter for each line (80)
  61. ;    DS = used to index screen at 'b8000'
  62. ;   These regs must be preserved during routine
  63. ;      (increment each line by adding '14' hex to ds for para
  64. ;        boundary of 320 bytes '140')
  65. ; **************  2 mode *********************
  66. ;    DH = count of 40 (physical lines)
  67. ;    CX = counter for each line (100)
  68. ;    SI = index to screen via ds
  69. ;   These regs must be preserved during routine
  70. ;    all output to printer is done from routine -send2-, which uses
  71. ;    bios routine int 17h, and provides safe error exit.
  72. ;
  73. ;  GRAF.COM is designed with the idea that the user's main program is the
  74. ;  primary function and GRAF.COM should not cause problems of its own.
  75. ;  The author has tried his best to send control back to the main program in
  76. ;  the case of errors involving the printer, and to make the program as easy
  77. ;  to use as possible.
  78. ;
  79. ; =======================================================
  80. ; =        USER MODIFICATION SECTION.        =
  81. ; =    If your printer can treat a byte of data to    =
  82. ; =    control the wires on the dot-matrix head you    =
  83. ; =    can probably get this working with your printer =
  84. ; =    If you have Epson Graftrax or a C.Itoh 8510a,    =
  85. ; =    just set the two equates indicated to -true-    =
  86. ; =    and compile. Otherwise get out your manual    =
  87. ; =    and put the code indicated in the -other-    =
  88. ; =    section and set -other- to -true-.        =
  89. ; =    **>    The title message starts at label    =
  90. ; =    **>    -buffer-. If you set for another    =
  91. ; =    **>    printer you should change the        =
  92. ; =    **>    greeting to indicate which printer    =
  93. ; =    ===> ONLY SET *ONE* CONDITION TO -TRUE- or you    =
  94. ; =    will have a real mess!        marty smith    =
  95. ; =======================================================
  96.  
  97. TRUE    EQU    1    ; DON'T CHANGE THESE!
  98. FALSE    EQU    0
  99.  
  100. ; ===============>  A L L  U S E R S  <===================
  101. ; ====> SET ONE AND ONLY ONE OF THE FOLLOWING THREE <=====
  102.  
  103. EPSON    EQU    TRUE
  104. CITOH    EQU    FALSE
  105. OTHER    EQU    FALSE
  106.  
  107. ; Each bit of a byte is mapped to the wire head of the printer.
  108. ; If the Epson MX is sent 80h (bit 7), the TOP wire makes a dot.
  109. ; If the C.ITOH is sent   01h (bit 0), the TOP wire makes a dot.
  110. ; ===============>  A L L  U S E R S  <===================
  111. ; =====> SET ONE AND ONLY ONE OF THE FOLLOWING TWO <======
  112.  
  113. BIT7    EQU    TRUE
  114. BIT0    EQU    FALSE
  115.     ; BIT7 is TRUE for EPSON
  116.     ; BIT0 is TRUE for CITOH
  117.  
  118. ; *****************************
  119. ; *  START of -OTHER- SECTION *
  120. ; *****************************
  121. ;
  122. ; ALL routines must set either BIT7 or BIT0.
  123. ;   above. If your printer can't see bit 7 or 0 as the top wire, you
  124. ;   will probably have quite a time getting this routine to work.
  125. ;
  126. ; OLINE Resets line spacing so that the print head
  127. ; will make a continuous line DOWN the page.
  128. ; This is the sequence to set the EPSON for this. (ESC A 8)
  129. ; SEND2 sends the byte in AL to the printer for ALL routines.
  130. ; It uses the INT 17h routine in order to avoid DOS's extra line
  131. ; feeds and CR's. Set for LPT1: Change SEND2 to redirect. DX=0=LPT1,1=LPT2
  132. OLINE    MACRO
  133.     MOV    AL,27
  134.     CALL    SEND2
  135.     MOV    AL,65
  136.     CALL    SEND2
  137.     MOV    AL,8
  138.     CALL    SEND2
  139.     ENDM
  140.  
  141. ; ORLINE restores the printer to normal line spacing
  142. ; Example is for EPSON (ESC 2)
  143. ORLINE    MACRO
  144.     MOV    AL,27
  145.     CALL    SEND2
  146.     MOV    AL,'2'
  147.     CALL    SEND2
  148.     ENDM
  149.  
  150. ; ORESET reinitializes the printer to default settings, spacings,
  151. ; current line becomes Top of Form.
  152. ; Is used by LARGE print to allow a series to be printed
  153. ; on separate pages. It can be modified by getting rid of label
  154. ; TOF: up to but not including     JMP DONE, which is the exit from
  155. ; the whole routine. Example is for EPSON. (ESC @)
  156. ORESET    MACRO
  157.     MOV    AL,27
  158.     CALL    SEND2
  159.     MOV    AL,'@'
  160.     CALL    SEND2
  161.     ENDM
  162.  
  163. ; BP1 initiates bit-plot graphics. It tells the printer
  164. ; that the next xxx bytes are to be considered bit-plots and not
  165. ; regular characters. The small print routine sends 320 bit plot bytes
  166. ; to the printer. On the EPSON this is:
  167. ; ESC K 64 1   hex 1b 4b 40 1  > 1*256+64=320
  168. ; --> the first part indents the page with ordinary spaces
  169. ; --> to find spaces take TOTAL_DOTS_PER_LINE - 320. Then / BITS_PER_CHARACTER
  170. ; --> Divide this by two and you have the spaces to indent
  171. BP1    MACRO
  172.     MOV    CX,13    ; EPSON ( we've got 320 dots and 480 to work with
  173. INLOP:    MOV    AL,20H    ; 480-320=160 / 6 dots per char. = 26.67 extra
  174.     CALL    SEND2    ; so indent the picture 13 spaces to center
  175.     LOOP    INLOP
  176.     MOV    AL,27
  177.     CALL    SEND2
  178.     MOV    AL,75
  179.     CALL    SEND2
  180.     MOV    AL,64
  181.     CALL    SEND2
  182.     MOV    AL,1
  183.     CALL    SEND2
  184.     ENDM
  185.  
  186. ; BP2.
  187. ; The LARGE print sends 400 bit plot bytes to the printer. On the EPSON:
  188. ; ESC K 144 1  hex 1b 4b 90 1  > 1*256+144=400
  189. ; FIND YOUR INDENT FOR 400 BITS
  190. BP2    MACRO
  191.     MOV    CX,6    ; EPSON ( we've got 400 dots and 480 to work with
  192. INLOP2: MOV    AL,20H    ; 480-400=80 / 6 dots per char. = 13.33 extra
  193.     CALL    SEND2    ; so indent the picture 6 spaces to center
  194.     LOOP    INLOP2
  195.     MOV    AL,27
  196.     CALL    SEND2
  197.     MOV    AL,75
  198.     CALL    SEND2
  199.     MOV    AL,144
  200.     CALL    SEND2
  201.     MOV    AL,1
  202.     CALL    SEND2
  203.     ENDM
  204.  
  205. ; ****************************
  206. ; *   END OF -OTHER- SECTION *
  207. ; ****************************
  208.  
  209. ;  ***************> START OF ACTUAL CODE <*****************
  210.  
  211. CSEG    SEGMENT 'CODE'
  212.     ASSUME CS:CSEG
  213.     ORG    100H        ; set up for .COM conversion
  214. INIT    PROC    FAR        ; we're an interrupt routine
  215.     JMP    INITIAL     ; so we have to set up first
  216. BUFFER    DB    '         GRAFTRAX.COM v1.2',10,13
  217.     DB    'EPSON MX-80 GRAFTRAX(tm) Screen Printer.',13,10
  218.     DB    '   Left Sh. PrtSc. = LARGE GRAPHICS',13,10
  219.     DB    '  Right Sh. PrtSc. = small graphics',13,10
  220.     DB    ' Text screen uses regular ROM routine.',13,10
  221.     DB    '   ESCape will exit GRAPHICS print.',13,10,'$'
  222. GOWAIT    DW    0
  223. WHERESI DW    0
  224. PTFLAG    DB    0
  225. ONEOR2    DB    0
  226. DSTOR    DW    0
  227. FUDGE    DD    0
  228. INITIAL:
  229.     MOV    AX,0    ; GET ADDR OF
  230.     MOV    DS,AX    ; PRINT SCREEN ROUTINE
  231.     MOV    SI,14H    ; IN ROM
  232.     MOV    AX,[SI] ; from interrupt table in ram
  233.     MOV    DX,AX    ; in case they change the ROM's!
  234.     INC    SI
  235.     INC    SI
  236.     MOV    AX,[SI]
  237.     MOV    DS,AX
  238.     MOV    AL,0F1H ; MOVE IT TO
  239.     MOV    AH,25H
  240.     INT    21H    ; INT F1H described in Tech. Manual as unused vector
  241.     MOV    AX,CS    ; RESET INT 5
  242.     MOV    DS,AX    ; TO POINT TO
  243.     MOV    AX,OFFSET START ; THIS ROUTINE
  244.     MOV    DX,AX
  245.     MOV    AL,5
  246.     MOV    AH,25H    ; DOS routine to reset int. vector
  247.     INT    21H
  248.     MOV    AX,CS
  249.     MOV    DS,AX
  250.     MOV    AX,OFFSET BUFFER
  251.     MOV    DX,AX
  252.     MOV    AH,9
  253.     INT    21H    ; PRINT GREETING
  254.     MOV    AX,OFFSET LAST    ; last address here
  255.     MOV    DX,AX
  256.     INC    DX
  257.     INT    27H    ; TERMINATE BUT STAY RESIDENT
  258. INIT    ENDP
  259. ; --->    ACTUAL INTERRUPT ROUTINE STARTS HERE  <---
  260. START    PROC    FAR    ; Start of main routine--Shift Prt.Sc hit.
  261.     ASSUME CS:CSEG
  262.     STI        ; This follows ROM routine real close
  263.     PUSH    DS
  264.     PUSH    AX    ;SAVE REGS
  265.     PUSH    BX
  266.     PUSH    CX
  267.     PUSH    DX
  268.     PUSH    DI
  269.     PUSH    SI
  270.     PUSH    BP
  271.     MOV    BP,SP    ; Save in case of error for reset
  272.     MOV    AX,50H    ; Check here first to see if
  273.     MOV    DS,AX    ; routine is already in progress
  274.     MOV    SI,0    ; otherwise it will be a mess.
  275.     MOV    AL,01H
  276.     CMP    [SI],AL
  277.     JNZ    NXTS    ; if not we're go for routine
  278.     JMP    EXIT    ; otherwise go back home.
  279. NXTS:    MOV    [SI],AL ; if we're go don't let us start again until done.
  280.     MOV    AH,15    ; Get the current video state.
  281.     INT    10H    ; from the ROM routine,
  282.     CMP    AL,4    ; AL=4-6 are all graphics so we're OK
  283.     JZ    GRAPHIC
  284.     CMP    AL,5
  285.     JZ    GRAPHIC
  286.     CMP    AL,6
  287.     JZ    GRAPHIC
  288.     MOV    AL,0    ; else reset and go to ROM routine.
  289.     MOV    [SI],AL
  290.     INT    0F1H    ; this is where we stored the ROM routine entry.
  291.     JMP    EXIT    ; Do the ROM routine but come back here to leave.
  292. GRAPHIC:
  293.     MOV    AX,40H    ; Get the keyboard shift flag
  294.     MOV    DS,AX    ; segment
  295.     MOV    SI,17H    ; and address
  296.     MOV    AX,[SI] ; pick it up
  297.     AND    AX,3    ; get rid of other stuff
  298.     CMP    AX,0    ; Mod. to create default small
  299.     JNZ    GR1    ; for case where routine is called as
  300.     MOV    AX,1    ; a subroutine.
  301. GR1:    MOV    CS:ONEOR2,AL    ; store for later
  302.     PUSH    AX    ; also here
  303.     MOV    AL,0    ; make sure this starts out as NO print.
  304.     MOV    CS:PTFLAG,AL
  305.     MOV    DL,00H    ; These bits indicate whether R or L Shift is down
  306.     MOV    DH,19H    ; 25 lines of graphic dots at 8 dots per line
  307.     MOV    AX,0B800H ; stored in DX
  308.     MOV    DS,AX    ;SET UP FOR SCREEN PEEK
  309. ; Printer setup section to change line spacing to 8/72" for continuous dots
  310.     IF    EPSON
  311.     MOV    AL,27    ; ESC
  312.     CALL    SEND2    ; goes out through INT 17h to avoid DOS processing
  313.     MOV    AL,65    ; A
  314.     CALL    SEND2
  315.     MOV    AL,8    ; 8
  316.     CALL    SEND2
  317.     ENDIF
  318.     IF    CITOH    ; ESC T 16
  319.     MOV    AL,27    ; ESC
  320.     CALL    SEND2    ; goes out through INT 17h to avoid DOS processing
  321.     MOV    AL,'T'  ; T
  322.     CALL    SEND2
  323.     MOV    AL,'1'  ; 1
  324.     CALL    SEND2
  325.     MOV    AL,'6'  ; 6
  326.     CALL    SEND2
  327.     MOV    AL,27
  328.     CALL    SEND2
  329.     MOV    AL,62    ; Set printer to unidirectional for dot alignment
  330.     CALL    SEND2
  331.     ENDIF
  332.     IF    OTHER
  333.     OLINE
  334.     ENDIF
  335.     POP    AX    ; get back which routine
  336.     CMP    AL,2    ; Left Shift Prt Sc means LARGE graphic print
  337.     JZ    MAIN2    ; so hop over there if so.
  338. ; START OF small GRAPHICS PRINT ROUTINE.
  339. ; This routine scans across the screen from left to right,
  340. ; building an EPSON bit plot byte out of IBM screen dots.
  341. ; EPSON wire head        IBM screen color dots
  342. ; TOP     o  128  80h bit 7    | 00 | 01 | 10 | 11 | = 4 dots, one byte
  343. ;     o   64  40h  "  6
  344. ; one     o   32  20h  "  5      ibm dots go one raster line then the next
  345. ; bit     o   16  10h  "  4      EVEN line, ie 0, 2, 4 etc.
  346. ; plot     o    8  08h  "  3
  347. ; byte     o    4  04h  "  2      then you go back and do 1, 3, 5 etc.
  348. ;     o    2  02h  "  1
  349. ; BOTTOM o    1  01h  "  0      At loc. 0000h are 4 dots, 0,0|0,1|0,2|0,3
  350. ;                At loc. 2000h are 4 dots, 1,0|1,1|1,2|1,3
  351. ;
  352. MAIN:    MOV    CX,80    ; 80 x 4 = 320 dots.
  353. MLOOP:    MOV    DL,0C0H ; 11000000b
  354.     CALL    TST4    ; see if this comes back <> 0
  355.     MOV    AL,AH    ; we are testing bit patterns for one screen byte
  356.     CALL    SEND    ; don't send to printer unless something to send
  357.     MOV    DL,30H    ; 00110000b
  358.     CALL    TST4    ; each byte is 4 dots
  359.     MOV    AL,AH    ; so we test for each dot in a byte
  360.     CALL    SEND    ; send sets PTFLAG if there is a dot on the line
  361.     MOV    DL,0CH    ; 00001100b
  362.     CALL    TST4    ; then resets to start of line and starts printing
  363.     MOV    AL,AH    ; AL is the bit plot byte being built
  364.     CALL    SEND
  365.     MOV    DL,03H    ; 00000011b
  366.     CALL    TST4    ; TST4 scans down 8 screen dot lines each time called
  367.     MOV    AL,AH
  368.     CALL    SEND
  369.     LOOP    MLOOP    ; 80 bytes make 320 dots
  370.     CALL    LFCR    ; this is a good old regular line feed/carriage return
  371.     CALL    BREAK?    ; see if someone hit ESC key. If so take early exit
  372.     OR    AL,AL
  373.     DEC    DH    ; DL is line counter
  374.     CMP    DH,0    ; when it goes 0 we're through
  375.     JZ    DONE    ; reset everything and do an IRET
  376.     MOV    AX,DS    ; otherwise bump the SEGMENT reg so that location
  377.     ADD    AX,14H    ; 0 is the start of the next line
  378.     MOV    DS,AX    ; X'140' = 320
  379.     JMP    MAIN    ; and do this 80 times (80x4=320)
  380. DONE:    MOV    AX,0
  381. ; This is the common exit for both routines, Printer is restored.
  382. DONE1:    PUSH    AX    ; save AX cause it has error exit flag
  383. ; EPSON command to reset printer to 6 lines/in. = ESC 2 (1b 32)
  384.     IF    EPSON
  385.     MOV    AL,27    ; RESET PRINTER, RESTORE REGS
  386.     CALL    SEND2
  387.     MOV    AL,32H
  388.     CALL    SEND2
  389.     ENDIF
  390. ; FOR CITOH MAKE SURE BIDIRECTIONAL PRINTING IS RESTORED
  391.     IF    CITOH
  392.     MOV    AL,27
  393.     CALL    SEND2
  394.     MOV    AL,'A'
  395.     CALL    SEND2
  396.     MOV    AL,27
  397.     CALL    SEND2
  398.     MOV    AL,60
  399.     CALL    SEND2
  400.     ENDIF
  401.     IF    OTHER
  402.     ORLINE
  403.     ENDIF
  404. EDONE:    MOV    AX,50H    ; Set end of PrtSc indication
  405.     MOV    DS,AX    ; OK to come back and do again
  406.     MOV    SI,0
  407.     POP    AX
  408.     MOV    [SI],AL
  409. EXIT:    POP    BP
  410.     POP    SI    ; restore regs and return to caller
  411.     POP    DI
  412.     POP    DX
  413.     POP    CX
  414.     POP    BX
  415.     POP    AX
  416.     POP    DS
  417.     IRET        ; were an interrupt routine so we IRET
  418. ; START OF LARGE PRINT ROUTINE
  419. ; +-------------+
  420. ; | ^ ^     |  This time we scan from 199,0 to 0,0
  421. ; | ^ ^     |  and go across
  422. ; | ^ ^     |  o  o    x  x    o  x    x  x   These are representations
  423. ; | | |     |  o  o    o  o    x  o    x  x   of one color dot.
  424. ; +-------------+    0         1         2         3       Palettes
  425. MAIN2:    MOV    DH,80    ; we have 80 colunms x 25 lines here
  426.     MOV    CS:WHERESI,3EF0H ; SI is our index
  427.     MOV    SI,CS:WHERESI
  428. MAIN2A: MOV    CX,64H    ; 100
  429. MLOOP2: MOV    AL,[SI] ; idea is to get a byte starting at screen BOTTOM
  430.     IF    BIT0
  431.     CALL    REVERSE ; Bits have to be reversed on wire 0 type
  432.     ENDIF
  433.     CALL    SEND    ; send it since these resemble bit plot bytes
  434.     CALL    FLIPFLOP ; then reverse(sort of) this byte and send it
  435.     CALL    SEND    ; again.
  436.     MOV    CS:GOWAIT,SI ; store SI for next EVEN raster line
  437.     SUB    SI,2000H ; subtract 2000h for the next ODD raster line
  438.     MOV    AL,[SI] ; and do the same here
  439.     IF    BIT0
  440.     CALL    REVERSE
  441.     ENDIF
  442.     CALL    SEND
  443.     CALL    FLIPFLOP
  444.     CALL    SEND
  445.     MOV    SI,CS:GOWAIT ; get back the EVEN line
  446.     SUB    SI,80    ; advance UP the screen one line (say 199,0 to 197,0)
  447.     LOOP    MLOOP2    ; and do this 100 times
  448.     CALL    LFCR    ; finished with one line we send normal line-end
  449.     CALL    BREAK?    ; check for an ESC if we want to abort
  450.     OR    AL,AL    ; clear flags
  451.     DEC    DH    ; DH is our line counter,
  452.     CMP    DH,0    ; when it goes 0 we're done.
  453.     JZ    TOF    ; so we'll try to reset Top of Form and exit
  454.     INC    CS:WHERESI    ; else go to the next byte location
  455.     MOV    SI,CS:WHERESI    ; store
  456.     JMP    MAIN2A        ; and do again
  457. TOF:    MOV    CX,19    ; tof restores page to 11 inches from where it started
  458. TOFL:    MOV    AL,13    ; send a bunch of cr's and lf's
  459.     CALL    SEND2    ; put BREAK? in here somehow
  460.     MOV    AL,10
  461.     CALL    SEND2
  462.     CALL    BREAK?    ; check for early exit
  463.     LOOP    TOFL    ; on and on.
  464. ; This restores the EPSON to 6 lines per inch
  465. ; ESC @ = Restore all settings to default
  466.     IF    EPSON
  467.     MOV    AL,27    ; esc
  468.     CALL    SEND2
  469.     MOV    AL,64    ; @
  470.     CALL    SEND2
  471.     ENDIF
  472. ;    IF    CITOH    ; No equivalent to Epson ESC @
  473. ;    MOV    AL,27    ; for CITOH
  474. ;    CALL    SEND2    ; so just reset line feed pitch
  475. ;    MOV    AL,'A'  ; this is done by DONE anyway
  476. ;    CALL    SEND2    ; so leave open if someone wants to patch
  477. ;    ENDIF
  478.     IF    OTHER
  479.     ORESET
  480.     ENDIF
  481.     JMP    DONE    ; clean up and back to caller.
  482. START    ENDP
  483. SEND2    PROC    NEAR    ; BIOS routine to print the character in AL
  484.     PUSH    AX
  485.     MOV    AH,00H    ; 0=print, 1=initialize port, 2=read status to AH
  486.     PUSH    DX
  487.     MOV    DX,0    ; DX specifies printer 0 (LPT1:)
  488.     INT    17H    ; BIOS used instead of DOS because DOS sends
  489.     POP    DX    ; CR/LF's in the middle of the bit-plots
  490.     TEST    AH,29h    ; check for timeout or errors or out-of-paper
  491.     POP    AX
  492.     JNZ    ERRET
  493.     RET
  494. ERRET:    MOV    AX,00FFH ; Flag for printer foulup
  495.     MOV    SP,BP
  496.     PUSH    AX
  497.     JMP    EDONE    ; special abort
  498. SEND2    ENDP
  499. ; EPSON bit plots operate at 480 or 960 dots across the page
  500. ; called by ESC K 'low byte';'high byte'
  501. ;  i.e.  300 dots would be 256+44 or 012CH
  502. ;  This is sent to the EPSON as --> 1b 4b 2c 01
  503. ;        or in decimal    --> 27 75 44 1
  504. INDENT    PROC    NEAR
  505.     PUSH    CX    ; 13 SPACES IN TO CENTER
  506.     IF    EPSON
  507.     MOV    CX,13    ; PICTURE ( we've got 320 dots and 480 to work with
  508. INLOP:    MOV    AL,20H    ; 480-320=160 / 6 dots per char. = 26.67 extra
  509.     CALL    SEND2    ; so indent the picture 13 spaces to center
  510.     LOOP    INLOP
  511. ; ESC K 64 1  = 256+64=320 bit plot type bytes on the way
  512.     MOV    AL,27    ; SEQUENCE TO SET UP 320
  513.     CALL    SEND2    ; BIT PLOTS IN 480 MODE
  514.     MOV    AL,75    ; OF MX-80
  515.     CALL    SEND2    ; This is the set-up for the small print
  516.     MOV    AL,64
  517.     CALL    SEND2
  518.     MOV    AL,1
  519.     CALL    SEND2
  520.     ENDIF
  521.     IF    CITOH
  522.     MOV    AL,27    ; ESC N = Pica pitch
  523.     CALL    SEND2
  524.     MOV    AL,'N'
  525.     CALL    SEND2
  526.     MOV    CX,20    ; PICTURE ( we've got 320 dots and 640 to work with
  527. INLOP:    MOV    AL,20H    ; 640-320=320 / 8 dots per char. = 40 extra
  528.     CALL    SEND2    ; so indent the picture 13 spaces to center
  529.     LOOP    INLOP
  530. ; ESC S 0320 = 320 bit plot type bytes on the way
  531.     MOV    AL,27    ; SEQUENCE TO SET UP 320
  532.     CALL    SEND2    ; BIT PLOTS IN 640 MODE
  533.     MOV    AL,'S'  ; OF CITOH
  534.     CALL    SEND2    ; This is the set-up for the small print
  535.     MOV    AL,'0'  ; Would love to try to use all 640 bits here
  536.     CALL    SEND2    ; but have no way of testing routine.
  537.     MOV    AL,'3'
  538.     CALL    SEND2
  539.     MOV    AL,'2'
  540.     CALL    SEND2
  541.     MOV    AL,'0'
  542.     CALL    SEND2
  543.     ENDIF
  544.     IF    OTHER
  545.     BP1
  546.     ENDIF
  547.     POP    CX
  548.     RET
  549. INDENT    ENDP
  550. ; This is indent for LARGE print
  551. ; This time we have 400 bit plots to send (200 lines x 2)
  552. ; 480-400=80 / 6 = 13.3 extra
  553. INDENT2 PROC    NEAR
  554.     PUSH    CX
  555.     IF    EPSON
  556.     MOV    CX,6    ; so indent 6 character type spaces
  557. INLOP2: MOV    AL,20H
  558.     CALL    SEND2
  559.     LOOP    INLOP2
  560. ; ESC 27 K 144 1 = 256+144=400 bit-plots
  561.     MOV    AL,27
  562.     CALL    SEND2
  563.     MOV    AL,75
  564.     CALL    SEND2
  565.     MOV    AL,144
  566.     CALL    SEND2
  567.     MOV    AL,1
  568.     CALL    SEND2
  569.     ENDIF
  570. ; 640-400=240 / 8 = 30 EXTRA characters
  571.     IF    CITOH
  572.     MOV    AL,27    ; ESC N = Pica pitch
  573.     CALL    SEND2
  574.     MOV    AL,'N'
  575.     CALL    SEND2
  576.     MOV    CX,15    ; PICTURE ( we've got 400 dots and 640 to work with
  577. INLOP2: MOV    AL,20H    ; 640-400 / 8 dots per char. = 30 extra
  578.     CALL    SEND2    ; so indent the picture 15 spaces to center
  579.     LOOP    INLOP2
  580. ; ESC S 0400 = 400 bit plot type bytes on the way
  581.     MOV    AL,27    ; SEQUENCE TO SET UP 400
  582.     CALL    SEND2    ; BIT PLOTS IN 640 MODE
  583.     MOV    AL,'S'  ; OF CITOH
  584.     CALL    SEND2
  585.     MOV    AL,'0'
  586.     CALL    SEND2
  587.     MOV    AL,'4'
  588.     CALL    SEND2
  589.     MOV    AL,'0'
  590.     CALL    SEND2
  591.     MOV    AL,'0'
  592.     CALL    SEND2
  593.     ENDIF
  594.     IF    OTHER
  595.     BP2
  596.     ENDIF
  597.     POP    CX
  598.     RET
  599. INDENT2 ENDP
  600. TST4    PROC    NEAR    ;  This routine builds ONE bit plot byte
  601.     MOV    AX,80    ;  by testing a dot with the mask sent
  602.     SUB    AX,CX    ;  from MLOOP.
  603.     MOV    SI,AX    ;  First it does the ODD row then the EVEN
  604.     MOV    AH,0    ;  since alternate lines are offset 2000h
  605.     MOV    AL,[SI] ;  from each other in memory.
  606.     AND    AL,DL    ;  DL has the mask
  607.     CMP    AL,0    ;  SI the location
  608.     JZ    NO7    ;  AL the memory byte
  609.     CALL    SET7    ;  AH is the byte being built
  610. NO7:    ADD    SI,80    ; +80 gets us from say 0,0 to 2,0
  611.     MOV    AL,[SI] ; get the memory byte ( 4 dots )
  612.     AND    AL,DL    ; get rid of dots we aren't testing now
  613.     CMP    AL,0    ; see if its COLOR 0
  614.     JZ    NO5    ; if yes, go on
  615.     CALL    SET5    ; otherwise set that bit
  616. NO5:    ADD    SI,80    ; continue 7 5 3 1
  617.     MOV    AL,[SI]
  618.     AND    AL,DL
  619.     CMP    AL,0
  620.     JZ    NO3
  621.     CALL    SET3
  622. NO3:    ADD    SI,80
  623.     MOV    AL,[SI]
  624.     AND    AL,DL
  625.     CMP    AL,0
  626.     JZ    NO1
  627.     CALL    SET1
  628. NO1:    PUSH    AX
  629.     MOV    AX,80
  630.     SUB    AX,CX    ; CX counts our screen position
  631.     ADD    AX,2000H ; add 2000h for the EVEN rows
  632.     MOV    SI,AX    ; with seg set to B800h we can use SI like an
  633.     POP    AX    ; array pointer ( AH has our byte so don't lose )
  634.     MOV    AL,[SI] ; and continue with the same idea for 6 4 2 0
  635.     AND    AL,DL
  636.     CMP    AL,0
  637.     JZ    NO6
  638.     CALL    SET6
  639. NO6:    ADD    SI,80
  640.     MOV    AL,[SI]
  641.     AND    AL,DL
  642.     CMP    AL,0
  643.     JZ    NO4
  644.     CALL    SET4
  645. NO4:    ADD    SI,80
  646.     MOV    AL,[SI]
  647.     AND    AL,DL
  648.     CMP    AL,0
  649.     JZ    NO2
  650.     CALL    SET2
  651. NO2:    ADD    SI,80
  652.     MOV    AL,[SI]
  653.     AND    AL,DL
  654.     CMP    AL,0
  655.     JZ    NO0
  656.     CALL    SET0
  657. NO0:    RET
  658. ; where's my Z80 now
  659. ; reverse this table if your bit plots use bit 0 for the top wire
  660.     IF    BIT7
  661. SET7:    OR    AH,80H    ; top wire - bit 7
  662.     RET
  663. SET6:    OR    AH,40H    ; bit 6
  664.     RET
  665. SET5:    OR    AH,20H    ; bit 5
  666.     RET
  667. SET4:    OR    AH,10H    ; bit 4
  668.     RET
  669. SET3:    OR    AH,08H    ; bit 3
  670.     RET
  671. SET2:    OR    AH,04H    ; bit 2
  672.     RET
  673. SET1:    OR    AH,02H    ; bit 1
  674.     RET
  675. SET0:    OR    AH,01H    ; bit 0
  676.     RET
  677.     ENDIF
  678.     IF    BIT0
  679. SET7:    OR    AH,01H    ; top wire - bit 0
  680.     RET
  681. SET6:    OR    AH,02H    ; bit 1
  682.     RET
  683. SET5:    OR    AH,04H    ; bit 2
  684.     RET
  685. SET4:    OR    AH,08H    ; bit 3
  686.     RET
  687. SET3:    OR    AH,10H    ; bit 4
  688.     RET
  689. SET2:    OR    AH,20H    ; bit 5
  690.     RET
  691. SET1:    OR    AH,40H    ; bit 6
  692.     RET
  693. SET0:    OR    AH,80H    ; bit 7
  694.     RET
  695.     ENDIF
  696. TST4    ENDP
  697. ; This routine pre-scans a line to see if in fact there are any bit
  698. ; plots to send. The main routine will keep sending bytes here
  699. ; If a whole line of 0's are sent we avoid going through the
  700. ; set-up for bit-plot (i.e. slower movement) graphics when a CR/LF
  701. ; would take care of everything.
  702. ; If there IS something to send, PTFLAG is set, the current line
  703. ; position is set to 0, bit-plot is init., and bits are really sent to printer.
  704. SEND    PROC    NEAR
  705.     PUSH    AX    ; save the character
  706.     PUSH    DS    ; DS saved cause it points to lines
  707.     MOV    AX,CS    ; set seg for here
  708.     MOV    DS,AX    ; This was some of my first stuff with the 8088
  709.     POP    AX    ; and I see some needless complexity here now
  710.     MOV    CS:DSTOR,AX    ; but it works and if I mess with it
  711.     CMP    CS:PTFLAG,0FFH    ; its back to DEBUG.
  712.     JNZ    NOSEND    ; if PTFLAG isn't FFh we are still scanning
  713.     POP    AX    ; else get the char. in AL and print it
  714.     CALL    SEND2    ; this is the real out to printer routine
  715.     JMP    SHORT NOSET ; restore DS and return
  716. NOSEND: POP    AX    ; This is the SCAN routine
  717.     CMP    AL,0    ; get the char. > test for 0 > if so reset and go back
  718.     JZ    NOSET
  719.     MOV    AL,0FFH ; if <> 0
  720.     MOV    CS:PTFLAG,AL ; set PTFLAG to go
  721.     POP    AX    ;DISCARD RETURN
  722.     CMP    CS:ONEOR2,1 ; check which (small or LARGE)
  723.     JNZ    TWO    ; indent 6 or 13 depending on which routine
  724.     CALL    INDENT    ; indent also sets up bit-plot mode
  725.     CALL    NOSET    ; NOSET will restore DS to right pos.
  726.     JMP    MAIN    ; and do the line for real.
  727. TWO:    CALL    INDENT2 ; init. for LARGE
  728.     MOV    SI,CS:WHERESI    ; SI set back to start of line
  729.     CALL    NOSET    ; get right DS
  730.     JMP    MAIN2A    ; back to beginning
  731. NOSET:    PUSH    AX    ; routine to restore DS
  732.     MOV    AX,CS:DSTOR
  733.     MOV    DS,AX
  734.     POP    AX
  735.     RET
  736. SEND    ENDP
  737. LFCR    PROC    NEAR    ; send a regular CR/LF combo
  738.     MOV    AL,13
  739.     CALL    SEND2
  740.     MOV    AL,10
  741.     CALL    SEND2
  742.     MOV    AX,0
  743.     MOV    CS:PTFLAG,AL ; reset PTFLAG for next line
  744.     MOV    AX,CS:DSTOR  ; restore DS
  745.     MOV    DS,AX
  746.     RET        ; onward
  747. LFCR    ENDP
  748. BREAK?    PROC    NEAR    ; Test for early exit
  749.     PUSH    AX    ; don't lose any regs. here
  750.     PUSH    DX
  751.     MOV    AH,06H    ; call direct keyboard io (constat)
  752.     MOV    DL,0FFH ; if we got a char. go check it.
  753.     INT    21H
  754.     JNZ    GOBACK? ; if zero flag clear we have a character
  755. BCONT:    POP    DX    ; no char. return
  756.     POP    AX
  757.     RET
  758. GOBACK?:
  759.     CMP    AL,1BH    ; ESC
  760.     JZ    BACK    ; so go back, else return
  761.     JMP    SHORT BCONT    ; no ESC exit
  762. BACK:    POP    DX    ; ESC exit This doesn't check for Ctrl-Break
  763.     POP    AX    ; so if it is hit we save it for the caller to handle
  764.     POP    AX    ;DISCARD RETURN
  765.     JMP    DONE    ; and go back to orig. caller
  766. BREAK?    ENDP
  767. FLIPFLOP    PROC NEAR    ; This creates different combinations
  768.     PUSH    CX    ; of a box of four bit-plot dots for one color dot.
  769.     PUSH    BX    ; Don't lose any variables or loop counters
  770.     PUSH    AX
  771.     MOV    CL,2    ; AL has present bit-plot finished byte
  772.     MOV    BX,0
  773.     AND    AL,3    ; 00000011b
  774.     CALL    FLIP
  775.     ROR    BL,CL    ; 11000000b
  776.     POP    AX    ; basically rotate bits around for
  777.     PUSH    AX    ; o x
  778.     CALL    R2    ; x o    color 1
  779.     AND    AL,3    ; and
  780.     CALL    FLIP    ; o x
  781.     ROR    BL,CL    ; o x    color 2
  782.     POP    AX    ; instead of
  783.     PUSH    AX    ; x o
  784.     CALL    R4    ; x o    color 1
  785.     AND    AL,3    ; and
  786.     CALL    FLIP    ; o x
  787.     ROR    BL,CL    ; o x    color 2
  788.     POP    AX    ; which aren't to convincing as
  789.     CALL    R6    ; two different colors
  790.     AND    AL,3
  791.     CALL    FLIP
  792.     ROR    BL,CL
  793.     MOV    AL,BL
  794.     POP    BX
  795.     POP    CX
  796.     RET
  797. R6:    ROR    AL,CL
  798. R4:    ROR    AL,CL
  799. R2:    ROR    AL,CL
  800.     RET
  801. FLIP:    CMP    AL,3    ; make sure there are two dots for color 1 and 2
  802.     JNZ    FLIP2
  803.     OR    BL,3
  804. FLIP2:    CMP    AL,2
  805.     JNZ    FLIP3
  806.     OR    BL,1
  807. FLIP3:    CMP    AL,1
  808.     JNZ    FLIP4
  809.     OR    BL,1
  810. FLIP4:    RET
  811. FLIPFLOP    ENDP
  812. REVERSE PROC    NEAR    ; take AL and make bit 0 bit 7 , 1 - 6, etc
  813.     PUSH    DX    ; Save our counters and masks
  814.     PUSH    CX
  815.     MOV    DL,01H    ; 00000001B
  816.     MOV    DH,80H    ; 10000000B
  817.     MOV    AH,00H    ; start out blank
  818.     MOV    CX,8    ; set counter for 8 times through
  819. REV1:    TEST    AL,DL    ; see if bit is set
  820.     JZ    REV2    ; if not skip next step
  821.     OR    AH,DH    ; else set bit in AH
  822. REV2:    SHL    DL,1    ; shift left test bit
  823.     SHR    DH,1    ; shift right mask bit (pad other bits with 0)
  824.     LOOP    REV1    ; do this 8 times
  825.     MOV    AL,AH    ; and we have a reversed character.
  826.     POP    CX    ; get back these
  827.     POP    DX
  828.     RET        ; and back to caller
  829. REVERSE ENDP
  830. LAST    DW    0
  831. CSEG    ENDS
  832.     END    INIT
  833. sed